/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月29日
 */
package com.massyframework.beanskin.assembly;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import com.massyframework.beanskin.ModuleIdentifier;
import com.massyframework.beanskin.ModuleRepository;
import com.massyframework.beanskin.RequireLibraryDescriptor;
import com.massyframework.beanskin.RequireLibraryDescriptors;
import com.massyframework.beanskin.assembly.beans.BeanContextHandlerFactory;
import com.massyframework.beanskin.service.DependencyServiceDescriptor;
import com.massyframework.beanskin.service.DependencyServiceDescriptorBuilder;
import com.massyframework.beanskin.service.ExportServiceDescriptor;
import com.massyframework.beanskin.service.ExportServiceDescriptorBuilder;
import com.massyframework.beanskin.service.ServiceRepositoryFactory;
import com.massyframework.beanskin.util.classloading.ModuleClassLoader;
import com.massyframework.beanskin.util.version.VersionRange;

/**
 * 用于创建装配件实例的构建器
 * 
 * <p>
 * 对assembly.xml的解析结果，通过构建器创建对应的装配件。
 * @author huangkh
 *
 */
public interface AssemblyBuilder extends RequireLibraryDescriptors {
	
	/**
	 * 添加Bean实例
	 * @param beanName {@link String},bean名称
	 * @param bean {@link Object}, bean实例
	 * @return {@link AsssemblyConfigBuilder}
	 */
	AssemblyBuilder addBean(String beanName, Object bean);

	/**
	 * 添加配置文件位置
	 * @param configLocation {@link String},配置文件路径 
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addConfigLocation(String configLocation);
	
	/**
	 * 添加配置类
	 * @param value {@link Class},配置类
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addConfigType(Class<?> value);
		
	/**
	 * 添加依赖服务定义
	 * @param value {@link DependencyServiceDescriptor}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addDependencyService(DependencyServiceDescriptor<?> value);
	
	/**
	 * 添加依赖服务定义
	 * @param action {@link Consumer}, 依赖服务定义构建器的消费者
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addDependencyService(Consumer<DependencyServiceDescriptorBuilder> action);
	
	/**
	 * 添加依赖服务定义
	 * @param beanName {@link String}, bean名称
	 * @param requiredType {@link Class}, 依赖服务的类型
	 * @param filterString {@link String},过滤字符串
	 * @return {@link AssemblyBuilder}
	 */
	default AssemblyBuilder addDependencyService(String beanName, Class<?> requiredType, String filterString) {
		return this.addDependencyService( builder -> {
			builder.beanName(beanName)
				.requiredType(requiredType)
				.filterString(filterString);
		});
	}
	
	/**
	 * 添加输出服务定义
	 * @param value {@link ExportServiceDescriptor}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addExportService(ExportServiceDescriptor value);
	
	/**
	 * 添加输出服务定义
	 * @param action {@link Consumer}, 输出服务定义构建器的消费者
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addExportService(Consumer<ExportServiceDescriptorBuilder> action);
	
	
	
	/**
	 * 添加输出服务定义
	 * @param beanName {@link String},bean名称
	 * @param exportType {@link Class},输出服务类型
	 * @param props {@link Map},属性
	 * @return {@link AssemblyBuilder}
	 */
	default AssemblyBuilder addExportService(String beanName, Class<?> exportType, Map<String, Object> props) {
		return this.addExportService(beanName, new Class<?>[] {exportType}, props);
	}
	
	/**
	 * 添加输出服务定义
	 * @param beanName {@link String},bean名称
	 * @param exportTypes {@link Class},输出服务类型的数组
	 * @param props {@link Map},属性
	 * @return {@link AssemblyBuilder}
	 */
	default AssemblyBuilder addExportService(String beanName, Class<?>[] exportTypes, Map<String, Object> props) {
		return this.addExportService( builder-> {
			builder.addExportServices(exportTypes)
				.beanName(beanName)
				.properties(props);
		});
	}
		
	/**
	 * 添加依赖模块
	 * @param value {@link RequireLibraryDescriptor}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addRequireLibrary(RequireLibraryDescriptor value);
	
	/**
	 * 添加标签集
	 * @param value {@link Set}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder addTags(Set<String> value);
	
	/**
	 * 设置Bean容器
	 * <p>
	 * 根据该名称，可查找对应的{@link BeanContextHandlerFactory}工厂，用来创建Bean容器
	 * @param beanContextName {@link String}.bean容器名称
	 * @param versionRange {@link VersionRange}, 版本范围
	 * @param factory {@link BeanContextHandlerFactory}, bean容器处理器工厂
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder beanContext(String beanContextName, VersionRange versionRange, BeanContextHandlerFactory factory);
	
	/**
	 * 设置类加载器
	 * @param value {@link ModuleClassLoader}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder classLoader(ModuleClassLoader value);
	
	/**
	 * 设置模块简介
	 * @param value {@link String}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder description(String value);
	
	/**
	 * 设置解密公钥和要解密的类型
	 * @param publicKey {@link String},公钥
	 * @param x509Name {@link String},证书名称
	 * @param x509Entrypted {@link String},证书md5加密数据
	 * @param classNames {@link List}, 需要解密的类名集合
	 * @param scriptFileNames {@link List}, 需要解密的脚本文件
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder decryption(String publicKey, String x509Name, String x509Entrypted, List<String> classNames, List<String> scriptFileNames);
		
	/**
	 * 设置开发商
	 * @param shortName {@link String},简称
	 * @param name {@link String},全称
	 * @param homePage {@link String}, 主页
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder developer(String shortName, String name, String homePage);
	
	/**
	 * 设置模块标识符
	 * @param value {@link ModuleIdentifier}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder identifier(ModuleIdentifier value);
	
	/**
	 * 模块标识符
	 * @return {@link ModuleIdentifier}
	 */
	ModuleIdentifier getModuleIdentifier();
	
	/**
	 * 设置模块资源库
	 * @param value {@link ModuleRepository}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder moduleRepository(ModuleRepository value);
	
	/**
	 * 设置模块名称
	 * @param value {@link String}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder name(String value);
	
	/**
	 * 设置服务资源库工厂  
	 * @param facotry {@link ServiceRepositoryFactory}
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder serviceRepositoryFactory(ServiceRepositoryFactory facotry);
	
			
	/**
	 * 设置参数, 不支持对存在参数进行覆写。
	 * @param name {@link String},参数名
	 * @param value {@link String},参数值
	 * @return {@link AssemblyBuilder}
	 */
	default AssemblyBuilder setParameter(String name, String value) {
		return this.setParameter(name, value, null);
	}
	
	/**
	 * 设置参数, 不支持对存在参数进行覆写。
	 * @param name {@link String},参数名
	 * @param value {@link String},参数值
	 * @param action {@link Consumer},参数设置成功失败的回调方法,可以为null.
	 * @return {@link AssemblyBuilder}
	 */
	AssemblyBuilder setParameter(String name, String value, Consumer<Boolean> action);
	
	/**
	 * 设置Serlvet模型
	 * @param value {@link ServletModel}
	 * @return {@link  AssemblyBuilder}
	 */
	AssemblyBuilder setServletModel(ServletModel value);
	
	/**
	 * 构建装配件
	 * @return {@link Assembly}
	 */
	Assembly build();
	
}
